#ifndef __MANAGER__
#define __MANAGER__
#include <unordered_map>
#include "Logger.hpp"

/*
    为什么要存在单例日志管理类？
        日志输出,我们希望是在任意位置都可以进行，当我们创建了一个日志器之后就会
        受到日志器所在作用域的访问属性限制，想想test.cc中所写的测试用例
    因此我们需要创建一个日志管理类,且这个类是一个单例，这样的话，我们就可以在任意
    位置来通过管理器单例在任意位置,获取单例,进行日志输出

    基于这个思想,这也是为什么日志器的建造者模式,建造的对象是局部日志器和全局日志器
    而不是简单的异步日志器,同步日志器。
    未来你想要全局管理 同步日志器,或者是异步日志器,只需要创建好日志器后
    加入到管理器中即可
    

*/

namespace Log
{
    // 单例日志管理类 - 管理器
    /*
        作用：
            1.对创建的所有全局日志器进行管理
            2.可以在任意位置获取日志器进行输出
        扩展:
            默认创建一个日志器,落地方式是屏幕
        
        一定是存在多线程下的,所以一定是需要加锁的,保护线程安全
    */

    class LogManager
    {
    private:
        // 1.管理日志器
        // 需要对日志器进行添加,删除
        // 我们使用哈希,以日志器的名字为key进行存储
        std::unordered_map<std::string,Logger::ptr> _loggers;
        // 2.加锁保护
        std::mutex _mt;
        Logger::ptr _root_logger;//默认日志器 - 标准输出
        // 默认日志器是局部日志器，但是这个局部的生命周期是随 管理器单例的
    private:
        // 需要创建默认的日志器

        LogManager()
        {
            // 这里只能创建局部日志器不能创建全局日志器
            // 因为全局日志器中,存在一个操作将 日志器 添加到 管理器单例中
            // 这里是在默认构造函数, 还没有一个单例, 此时去创建全局日志器
            // 全局日志器那里,会存在构造单例,再进行添加,又会回到 lp(new GolbalLoggerBuilder)
            // 陷入死循环
            LoggerBuilder::ptr lp(new LocalLoggerBuilder);
            lp->BuildLoggerType(LoggerType::LOGGER_ASYNC);
            lp->BuildFormatter("%m%n");
            lp->BuildLimitLevel(LogType::DEBUG);
            std::string name = "root_logger";
            lp->BuildLoggerName(name);
            lp->BuildLoggerSinks<StdoutLogSink>();
            _root_logger = lp->Build();

            // 在c++11以上,这一定是线程安全的。
            // 因为c++11中static是线程安全的,它只会有一个线程进入默认构造
            // _loggers[name] = _root_logger;
            _loggers.insert(std::make_pair(name,_root_logger));
            // std::cout << "LogManager::默认日志器 创建成功" << std::endl; 
        }

        // 这种模式的单例,构造函数是不同删除的！不然你单例也构造不成！
        // 设置为私有就可以
        // LogManager() = delete;
        LogManager(const LogManager& lm) = delete;
        LogManager& operator=(const LogManager& lm) = delete;
    public:

        static LogManager& GetInstance()
        {
            static LogManager lm;
            return lm;
        }
        // 判断日志器是否存在
        bool HasLogger(const std::string& name)
        {
            auto pos = _loggers.find(name);
            if(pos == _loggers.end())
                return false;
            return true;
        }

        // 增加日志器
        void AddLogger(const std::string name,Logger::ptr logger)
        {
            // std::unique_lock<std::mutex>(_mt); // 这是匿名对象,生命周期只这有一行!!
            std::unique_lock<std::mutex> ulc(_mt); 
            _loggers[name] = logger;            
        }
        // 删除日志器
        void DelLogger(const std::string name)
        {
            // std::unique_lock<std::mutex>(_mt);
            std::unique_lock<std::mutex> ulc(_mt); 
            _loggers.erase(name);
        }
        // 获取日志器
        Logger::ptr GetLogger(const std::string name)
        {
            // std::unique_lock<std::mutex>(_mt);
            std::unique_lock<std::mutex> ulc(_mt);
            // 不能这么写,如果name不存在它会进行插入
            // 是不可以的
            // return _loggers[name];
            auto it = _loggers.find(name);
            if(it == _loggers.end())
            {
                return Logger::ptr(); //返回一个匿名对象
            }
            return it->second;
        }
        // 获取默认的日志器 - 标准输出的
        Logger::ptr GetRootLogger()
        {
            std::unique_lock<std::mutex> ulc(_mt);
            return _root_logger;
        }
    };
    //    std::unordered_map<std::string,Logger::ptr> LogManager::_loggers;
    //    std::mutex LogManager::_mt;

    
    class GlobalLoggerBuilder:public LoggerBuilder
    {
    public:
        Logger::ptr Build()
        {
            if(_sinks.empty())
            {
                std::cout << "GlobalLoggerBuilder::_sinks is empty" << std::endl;
                abort();
            }
            if(_fter.get() == nullptr)
            {
                std::cout << "GlobalLoggerBuilder::_fter is nullptr" << std::endl;
                abort();
            }
            if(_name.empty())
            {
                std::cout << "GlobalLoggerBuilder::_name is empty" << std::endl;
                abort();
            }

            Logger::ptr logger;
            if(_logger_type == LoggerType::LOGGER_ASYNC)
            {
                logger = std::shared_ptr<AsyncLogger>(new AsyncLogger\
                            (_sinks,_async_type,_fter,_name,_limit_level));
            }
            else
            {
                logger = std::make_shared<SyncLogger>(_sinks,_fter,_name,_limit_level);
            }
            // 添加到全局管理模块中
            LogManager::GetInstance().AddLogger(_name,logger);
            return logger;
        }

        // error
        // 1.并不是在GolbalLoggerBuilder类中把它设置成单例模式
        // 而是让它添加到 日志管理类中,这个日志管理类是一个单例

        // static Logger::ptr GetInstance()
        // {
        // }
        // GlobalLoggerBuilder() = delete;
        // GlobalLoggerBuilder(const GlobalLoggerBuilder& glb) = delete;
        // GlobalLoggerBuilder& operator=(const GlobalLoggerBuilder& glb) = delete;
    };


   
}


#endif